﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Utilities
{
    /// <summary>
    /// A class that manages a global low level keyboard hook
    /// </summary>
    class globalMouseHook
    {
        IntPtr mHook = IntPtr.Zero;
        public event EventHandler MouseAction = delegate { };

        public  void Hook()
        {
             SetHook();
        }
        public  void UnHook()
        {
            if(mHook!=IntPtr.Zero)
                UnhookWindowsHookEx(mHook);
        }
        ~globalMouseHook()
        {
            UnHook();
        }
        //private  LowLevelMouseProc _proc = HookCallback;

        private void SetHook()
        {
            /*using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_MOUSE_LL, proc,
                  GetModuleHandle(curModule.ModuleName), 0);
            }*/
            //-----------
            IntPtr hInstance = LoadLibrary("User32");
            mHook = SetWindowsHookEx(WH_MOUSE_LL, HookCallback, hInstance, 0);
        }

        private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
        
        /*private IntPtr MouseProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            return IntPtr.Zero;
        }*/


        

        private   IntPtr HookCallback(
          int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 &&
                ( MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
                || (MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam)
                )
            {
                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                //MouseAction(null, new MouseEventHandler());
                MouseAction(null, null);
                
            }
            //return CallNextHookEx(mHook, nCode, wParam, lParam);
            return mHook;
            //return IntPtr.Zero;// CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        private const int WH_MOUSE_LL = 14;

        private enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_MOUSEMOVE = 0x0200,
            WM_MOUSEWHEEL = 0x020A,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int x;
            public int y;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
          LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
          IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
    }
}